home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * *
- * HPACK Multi-System Archiver *
- * =========================== *
- * *
- * MD5 Message Digest Code *
- * MD5.C Updated 02/10/91 *
- * *
- * This program is protected by copyright and as such any use or copying of *
- * this code for your own purposes directly or indirectly is highly uncool *
- * and if you do so there will be....trubble. *
- * And remember: We know where your kids go to school. *
- * *
- * Copyright 1991 Peter C.Gutmann. All rights reserved *
- * *
- ****************************************************************************/
-
- #include <stdlib.h>
- #include <string.h>
- #ifdef __MAC__
- #include "md5.h"
- #else
- #include "crypt/md5.h"
- #endif /* __MAC__ */
-
- /****************************************************************************
- * *
- * Implementation RSA Data Security, Inc. MD5 Message-Digest Algorithm *
- * Created 2/17/90 RLR, revised 1/91 SRD,AJ,BSK,JT Reference C Version *
- * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved *
- * *
- ****************************************************************************/
-
- /* Define the following to use the assembly-language version of MDTransform().
- This is desirable since MDTransform() uses many rotates which cannot be
- easily represented in C and must be done inefficiently via shifts */
-
- #ifdef __MSDOS__
- #define ASM_MD5
- #endif /* __MSDOS__ */
-
- #ifdef ASM_MD5
- void MD5Transform( LONG *buf, LONG *in );
- #endif /* ASM_MD5 */
-
- /* To form the message digest for a message M, initialize a context buffer
- mdContext using MD5Init(); call MD5Update() on mdContext and M; and call
- MD5Final() on mdContext. The message digest is now in
- mdContext->digest[ 0 ... 15 ] */
-
- /****************************************************************************
- * *
- * The MD5 Transformation *
- * *
- ****************************************************************************/
-
- /* The Mysterious Constants used in the MD5 transformation */
-
- static LONG md5const[] = { 3614090360L, 3905402710L, 606105819L, 3250441966L,
- 4118548399L, 1200080426L, 2821735955L, 4249261313L,
- 1770035416L, 2336552879L, 4294925233L, 2304563134L,
- 1804603682L, 4254626195L, 2792965006L, 1236535329L,
- 4129170786L, 3225465664L, 643717713L, 3921069994L,
- 3593408605L, 38016083L, 3634488961L, 3889429448L,
- 568446438L, 3275163606L, 4107603335L, 1163531501L,
- 2850285829L, 4243563512L, 1735328473L, 2368359562L,
- 4294588738L, 2272392833L, 1839030562L, 4259657740L,
- 2763975236L, 1272893353L, 4139469664L, 3200236656L,
- 681279174L, 3936430074L, 3572445317L, 76029189L,
- 3654602809L, 3873151461L, 530742520L, 3299628645L,
- 4096336452L, 1126891415L, 2878612391L, 4237533241L,
- 1700485571L, 2399980690L, 4293915773L, 2240044497L,
- 1873313359L, 4264355552L, 2734768916L, 1309151649L,
- 4149444226L, 3174756917L, 718787259L, 3951481745L };
- /* Storage for the Mysterious Constants (either md5const or user-defined) */
-
- LONG mConst[ MD5_ROUNDS ];
-
- #ifndef ASM_MD5
-
- /* F, G, H and I are basic MD5 functions */
-
- #define F(X,Y,Z) ( ( X & Y ) | ( ~X & Z ) )
- #define G(X,Y,Z) ( ( X & Z ) | ( Y & ~Z ) )
- #define H(X,Y,Z) ( X ^ Y ^ Z )
- #define I(X,Y,Z) ( Y ^ ( X | ~Z ) )
-
- /* ROTATE_LEFT rotates x left n bits */
-
- #define ROTATE_LEFT(x,n) ( ( x << n ) | ( x >> ( 32 - n ) ) )
-
- /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is
- separate from addition to prevent recomputation */
-
- #define FF(A,B,C,D,X,shiftAmt,magicConst) \
- { \
- A += F( B, C, D ) + X + magicConst; \
- A = ROTATE_LEFT( A, shiftAmt ); \
- A += B; \
- }
-
- #define GG(A,B,C,D,X,shiftAmt,magicConst) \
- { \
- A += G( B, C, D ) + X + magicConst; \
- A = ROTATE_LEFT( A, shiftAmt ); \
- A += B; \
- }
-
- #define HH(A,B,C,D,X,shiftAmt,magicConst) \
- { \
- A += H( B, C, D ) + X + magicConst; \
- A = ROTATE_LEFT( A, shiftAmt ); \
- A += B; \
- }
-
- #define II(A,B,C,D,X,shiftAmt,magicConst) \
- { \
- A += I( B, C, D ) + X + magicConst; \
- A = ROTATE_LEFT( A, shiftAmt ); \
- A += B; \
- }
-
- /* Round 1 shift amounts */
-
- #define S11 7
- #define S12 12
- #define S13 17
- #define S14 22
-
- /* Round 2 shift amounts */
-
- #define S21 5
- #define S22 9
- #define S23 14
- #define S24 20
-
- /* Round 3 shift amounts */
-
- #define S31 4
- #define S32 11
- #define S33 16
- #define S34 23
-
- /* Round 4 shift amounts */
-
- #define S41 6
- #define S42 10
- #define S43 15
- #define S44 21
-
- /* Basic MD5 step. Transforms buf based on in. Note that if the Mysterious
- Constants are arranged backwards in little-endian order and decrypted with
- the DES they produce OCCULT MESSAGES! */
-
- #if defined( __ARC__ ) || defined( IRIX ) || defined( __TSC__ ) || defined( VCC )
-
- /* MD5Transform is split into its component rounds since many optimizers
- choke on the grand unified version */
-
- static void MD5TransformRound1( LONG *A, LONG *B, LONG *C, LONG *D, LONG *in )
- {
- /* Round 1 */
- FF( *A, *B, *C, *D, in[ 0 ], S11, mConst[ 0 ] ); /* 1 */
- FF( *D, *A, *B, *C, in[ 1 ], S12, mConst[ 1 ] ); /* 2 */
- FF( *C, *D, *A, *B, in[ 2 ], S13, mConst[ 2 ] ); /* 3 */
- FF( *B, *C, *D, *A, in[ 3 ], S14, mConst[ 3 ] ); /* 4 */
- FF( *A, *B, *C, *D, in[ 4 ], S11, mConst[ 4 ] ); /* 5 */
- FF( *D, *A, *B, *C, in[ 5 ], S12, mConst[ 5 ] ); /* 6 */
- FF( *C, *D, *A, *B, in[ 6 ], S13, mConst[ 6 ] ); /* 7 */
- FF( *B, *C, *D, *A, in[ 7 ], S14, mConst[ 7 ] ); /* 8 */
- FF( *A, *B, *C, *D, in[ 8 ], S11, mConst[ 8 ] ); /* 9 */
- FF( *D, *A, *B, *C, in[ 9 ], S12, mConst[ 9 ] ); /* 10 */
- FF( *C, *D, *A, *B, in[ 10 ], S13, mConst[ 10 ] ); /* 11 */
- FF( *B, *C, *D, *A, in[ 11 ], S14, mConst[ 11 ] ); /* 12 */
- FF( *A, *B, *C, *D, in[ 12 ], S11, mConst[ 12 ] ); /* 13 */
- FF( *D, *A, *B, *C, in[ 13 ], S12, mConst[ 13 ] ); /* 14 */
- FF( *C, *D, *A, *B, in[ 14 ], S13, mConst[ 14 ] ); /* 15 */
- FF( *B, *C, *D, *A, in[ 15 ], S14, mConst[ 15 ] ); /* 16 */
- }
-
- static void MD5TransformRound2( LONG *A, LONG *B, LONG *C, LONG *D, LONG *in )
- {
- /* Round 2 */
- GG( *A, *B, *C, *D, in[ 1 ], S21, mConst[ 16 ] ); /* 17 */
- GG( *D, *A, *B, *C, in[ 6 ], S22, mConst[ 17 ] ); /* 18 */
- GG( *C, *D, *A, *B, in[ 11 ], S23, mConst[ 18 ] ); /* 19 */
- GG( *B, *C, *D, *A, in[ 0 ], S24, mConst[ 19 ] ); /* 20 */
- GG( *A, *B, *C, *D, in[ 5 ], S21, mConst[ 20 ] ); /* 21 */
- GG( *D, *A, *B, *C, in[ 10 ], S22, mConst[ 21 ] ); /* 22 */
- GG( *C, *D, *A, *B, in[ 15 ], S23, mConst[ 22 ] ); /* 23 */
- GG( *B, *C, *D, *A, in[ 4 ], S24, mConst[ 23 ] ); /* 24 */
- GG( *A, *B, *C, *D, in[ 9 ], S21, mConst[ 24 ] ); /* 25 */
- GG( *D, *A, *B, *C, in[ 14 ], S22, mConst[ 25 ] ); /* 26 */
- GG( *C, *D, *A, *B, in[ 3 ], S23, mConst[ 26 ] ); /* 27 */
- GG( *B, *C, *D, *A, in[ 8 ], S24, mConst[ 27 ] ); /* 28 */
- GG( *A, *B, *C, *D, in[ 13 ], S21, mConst[ 28 ] ); /* 29 */
- GG( *D, *A, *B, *C, in[ 2 ], S22, mConst[ 29 ] ); /* 30 */
- GG( *C, *D, *A, *B, in[ 7 ], S23, mConst[ 30 ] ); /* 31 */
- GG( *B, *C, *D, *A, in[ 12 ], S24, mConst[ 31 ] ); /* 32 */
- }
-
- static void MD5TransformRound3( LONG *A, LONG *B, LONG *C, LONG *D, LONG *in )
- {
- /* Round 3 */
- HH( *A, *B, *C, *D, in[ 5 ], S31, mConst[ 32 ] ); /* 33 */
- HH( *D, *A, *B, *C, in[ 8 ], S32, mConst[ 33 ] ); /* 34 */
- HH( *C, *D, *A, *B, in[ 11 ], S33, mConst[ 34 ] ); /* 35 */
- HH( *B, *C, *D, *A, in[ 14 ], S34, mConst[ 35 ] ); /* 36 */
- HH( *A, *B, *C, *D, in[ 1 ], S31, mConst[ 36 ] ); /* 37 */
- HH( *D, *A, *B, *C, in[ 4 ], S32, mConst[ 37 ] ); /* 38 */
- HH( *C, *D, *A, *B, in[ 7 ], S33, mConst[ 38 ] ); /* 39 */
- HH( *B, *C, *D, *A, in[ 10 ], S34, mConst[ 39 ] ); /* 40 */
- HH( *A, *B, *C, *D, in[ 13 ], S31, mConst[ 40 ] ); /* 41 */
- HH( *D, *A, *B, *C, in[ 0 ], S32, mConst[ 41 ] ); /* 42 */
- HH( *C, *D, *A, *B, in[ 3 ], S33, mConst[ 42 ] ); /* 43 */
- HH( *B, *C, *D, *A, in[ 6 ], S34, mConst[ 43 ] ); /* 44 */
- HH( *A, *B, *C, *D, in[ 9 ], S31, mConst[ 44 ] ); /* 45 */
- HH( *D, *A, *B, *C, in[ 12 ], S32, mConst[ 45 ] ); /* 46 */
- HH( *C, *D, *A, *B, in[ 15 ], S33, mConst[ 46 ] ); /* 47 */
- HH( *B, *C, *D, *A, in[ 2 ], S34, mConst[ 47 ] ); /* 48 */
- }
-
- static void MD5TransformRound4( LONG *A, LONG *B, LONG *C, LONG *D, LONG *in )
- {
- /* Round 4 */
- II( *A, *B, *C, *D, in[ 0 ], S41, mConst[ 48 ] ); /* 49 */
- II( *D, *A, *B, *C, in[ 7 ], S42, mConst[ 49 ] ); /* 50 */
- II( *C, *D, *A, *B, in[ 14 ], S43, mConst[ 50 ] ); /* 51 */
- II( *B, *C, *D, *A, in[ 5 ], S44, mConst[ 51 ] ); /* 52 */
- II( *A, *B, *C, *D, in[ 12 ], S41, mConst[ 52 ] ); /* 53 */
- II( *D, *A, *B, *C, in[ 3 ], S42, mConst[ 53 ] ); /* 54 */
- II( *C, *D, *A, *B, in[ 10 ], S43, mConst[ 54 ] ); /* 55 */
- II( *B, *C, *D, *A, in[ 1 ], S44, mConst[ 55 ] ); /* 56 */
- II( *A, *B, *C, *D, in[ 8 ], S41, mConst[ 56 ] ); /* 57 */
- II( *D, *A, *B, *C, in[ 15 ], S42, mConst[ 57 ] ); /* 58 */
- II( *C, *D, *A, *B, in[ 6 ], S43, mConst[ 58 ] ); /* 59 */
- II( *B, *C, *D, *A, in[ 13 ], S44, mConst[ 59 ] ); /* 60 */
- II( *A, *B, *C, *D, in[ 4 ], S41, mConst[ 60 ] ); /* 61 */
- II( *D, *A, *B, *C, in[ 11 ], S42, mConst[ 61 ] ); /* 62 */
- II( *C, *D, *A, *B, in[ 2 ], S43, mConst[ 62 ] ); /* 63 */
- II( *B, *C, *D, *A, in[ 9 ], S44, mConst[ 63 ] ); /* 64 */
- }
-
- void MD5Transform( LONG *buf, LONG *in )
- {
- LONG A = buf[ 0 ], B = buf[ 1 ], C = buf[ 2 ], D = buf[ 3 ];
-
- MD5TransformRound1 (&A, &B, &C, &D, in);
- MD5TransformRound2 (&A, &B, &C, &D, in);
- MD5TransformRound3 (&A, &B, &C, &D, in);
- MD5TransformRound4 (&A, &B, &C, &D, in);
-
- buf[ 0 ] += A;
- buf[ 1 ] += B;
- buf[ 2 ] += C;
- buf[ 3 ] += D;
- }
-
- #else
-
- void MD5Transform( LONG *buf, LONG *in )
- {
- LONG A = buf[ 0 ], B = buf[ 1 ], C = buf[ 2 ], D = buf[ 3 ];
-
- /* Round 1 */
- FF( A, B, C, D, in[ 0 ], S11, mConst[ 0 ] ); /* 1 */
- FF( D, A, B, C, in[ 1 ], S12, mConst[ 1 ] ); /* 2 */
- FF( C, D, A, B, in[ 2 ], S13, mConst[ 2 ] ); /* 3 */
- FF( B, C, D, A, in[ 3 ], S14, mConst[ 3 ] ); /* 4 */
- FF( A, B, C, D, in[ 4 ], S11, mConst[ 4 ] ); /* 5 */
- FF( D, A, B, C, in[ 5 ], S12, mConst[ 5 ] ); /* 6 */
- FF( C, D, A, B, in[ 6 ], S13, mConst[ 6 ] ); /* 7 */
- FF( B, C, D, A, in[ 7 ], S14, mConst[ 7 ] ); /* 8 */
- FF( A, B, C, D, in[ 8 ], S11, mConst[ 8 ] ); /* 9 */
- FF( D, A, B, C, in[ 9 ], S12, mConst[ 9 ] ); /* 10 */
- FF( C, D, A, B, in[ 10 ], S13, mConst[ 10 ] ); /* 11 */
- FF( B, C, D, A, in[ 11 ], S14, mConst[ 11 ] ); /* 12 */
- FF( A, B, C, D, in[ 12 ], S11, mConst[ 12 ] ); /* 13 */
- FF( D, A, B, C, in[ 13 ], S12, mConst[ 13 ] ); /* 14 */
- FF( C, D, A, B, in[ 14 ], S13, mConst[ 14 ] ); /* 15 */
- FF( B, C, D, A, in[ 15 ], S14, mConst[ 15 ] ); /* 16 */
-
- /* Round 2 */
- GG( A, B, C, D, in[ 1 ], S21, mConst[ 16 ] ); /* 17 */
- GG( D, A, B, C, in[ 6 ], S22, mConst[ 17 ] ); /* 18 */
- GG( C, D, A, B, in[ 11 ], S23, mConst[ 18 ] ); /* 19 */
- GG( B, C, D, A, in[ 0 ], S24, mConst[ 19 ] ); /* 20 */
- GG( A, B, C, D, in[ 5 ], S21, mConst[ 20 ] ); /* 21 */
- GG( D, A, B, C, in[ 10 ], S22, mConst[ 21 ] ); /* 22 */
- GG( C, D, A, B, in[ 15 ], S23, mConst[ 22 ] ); /* 23 */
- GG( B, C, D, A, in[ 4 ], S24, mConst[ 23 ] ); /* 24 */
- GG( A, B, C, D, in[ 9 ], S21, mConst[ 24 ] ); /* 25 */
- GG( D, A, B, C, in[ 14 ], S22, mConst[ 25 ] ); /* 26 */
- GG( C, D, A, B, in[ 3 ], S23, mConst[ 26 ] ); /* 27 */
- GG( B, C, D, A, in[ 8 ], S24, mConst[ 27 ] ); /* 28 */
- GG( A, B, C, D, in[ 13 ], S21, mConst[ 28 ] ); /* 29 */
- GG( D, A, B, C, in[ 2 ], S22, mConst[ 29 ] ); /* 30 */
- GG( C, D, A, B, in[ 7 ], S23, mConst[ 30 ] ); /* 31 */
- GG( B, C, D, A, in[ 12 ], S24, mConst[ 31 ] ); /* 32 */
-
- /* Round 3 */
- HH( A, B, C, D, in[ 5 ], S31, mConst[ 32 ] ); /* 33 */
- HH( D, A, B, C, in[ 8 ], S32, mConst[ 33 ] ); /* 34 */
- HH( C, D, A, B, in[ 11 ], S33, mConst[ 34 ] ); /* 35 */
- HH( B, C, D, A, in[ 14 ], S34, mConst[ 35 ] ); /* 36 */
- HH( A, B, C, D, in[ 1 ], S31, mConst[ 36 ] ); /* 37 */
- HH( D, A, B, C, in[ 4 ], S32, mConst[ 37 ] ); /* 38 */
- HH( C, D, A, B, in[ 7 ], S33, mConst[ 38 ] ); /* 39 */
- HH( B, C, D, A, in[ 10 ], S34, mConst[ 39 ] ); /* 40 */
- HH( A, B, C, D, in[ 13 ], S31, mConst[ 40 ] ); /* 41 */
- HH( D, A, B, C, in[ 0 ], S32, mConst[ 41 ] ); /* 42 */
- HH( C, D, A, B, in[ 3 ], S33, mConst[ 42 ] ); /* 43 */
- HH( B, C, D, A, in[ 6 ], S34, mConst[ 43 ] ); /* 44 */
- HH( A, B, C, D, in[ 9 ], S31, mConst[ 44 ] ); /* 45 */
- HH( D, A, B, C, in[ 12 ], S32, mConst[ 45 ] ); /* 46 */
- HH( C, D, A, B, in[ 15 ], S33, mConst[ 46 ] ); /* 47 */
- HH( B, C, D, A, in[ 2 ], S34, mConst[ 47 ] ); /* 48 */
-
- /* Round 4 */
- II( A, B, C, D, in[ 0 ], S41, mConst[ 48 ] ); /* 49 */
- II( D, A, B, C, in[ 7 ], S42, mConst[ 49 ] ); /* 50 */
- II( C, D, A, B, in[ 14 ], S43, mConst[ 50 ] ); /* 51 */
- II( B, C, D, A, in[ 5 ], S44, mConst[ 51 ] ); /* 52 */
- II( A, B, C, D, in[ 12 ], S41, mConst[ 52 ] ); /* 53 */
- II( D, A, B, C, in[ 3 ], S42, mConst[ 53 ] ); /* 54 */
- II( C, D, A, B, in[ 10 ], S43, mConst[ 54 ] ); /* 55 */
- II( B, C, D, A, in[ 1 ], S44, mConst[ 55 ] ); /* 56 */
- II( A, B, C, D, in[ 8 ], S41, mConst[ 56 ] ); /* 57 */
- II( D, A, B, C, in[ 15 ], S42, mConst[ 57 ] ); /* 58 */
- II( C, D, A, B, in[ 6 ], S43, mConst[ 58 ] ); /* 59 */
- II( B, C, D, A, in[ 13 ], S44, mConst[ 59 ] ); /* 60 */
- II( A, B, C, D, in[ 4 ], S41, mConst[ 60 ] ); /* 61 */
- II( D, A, B, C, in[ 11 ], S42, mConst[ 61 ] ); /* 62 */
- II( C, D, A, B, in[ 2 ], S43, mConst[ 62 ] ); /* 63 */
- II( B, C, D, A, in[ 9 ], S44, mConst[ 63 ] ); /* 64 */
-
- buf[ 0 ] += A;
- buf[ 1 ] += B;
- buf[ 2 ] += C;
- buf[ 3 ] += D;
- }
- #endif /* __ARC__ || IRIX || __TSC__ || VCC */
-
- #endif /* ASM_MD5 */
-
- /****************************************************************************
- * *
- * MD5 Support Routines *
- * *
- ****************************************************************************/
-
- #ifdef LITTLE_ENDIAN
-
- #ifdef ASM_MD5
- void longReverse( LONG *buffer, int byteCount );
- #else
-
- /* When run on a little-endian CPU we need to perform byte reversal on an
- array of longwords. It is possible to make the code endianness-
- independant by fiddling around with data at the byte level, but this
- makes for very slow code, so we rely on the user to sort out endianness
- at compile time */
-
- void longReverse( LONG *buffer, int byteCount )
- {
- LONG value;
-
- byteCount /= sizeof( LONG );
- while( byteCount-- )
- {
- value = ( *buffer << 16 ) | ( *buffer >> 16 );
- *buffer++ = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 );
- }
- }
- #endif /* ASM_MD5 */
-
- #endif /* LITTLE_ENDIAN */
-
- /* The external buffer for saving the Mysterious Constants. Since the MD5/
- MDC code is dual-use, we need to save the constants whenever we switch
- from MDC to MD5 */
-
- extern BYTE *cryptBuffer;
-
- /* The routine MD5SetConst sets the Mysterious Constants to either the
- standard MD5 ones or to a user-defined set for MDC */
-
- static BOOLEAN isMD5const = FALSE;
-
- void MD5SetConst( BYTE *buffer )
- {
- if( buffer == NULL )
- {
- /* If the constants are already set up, don't bother re-setting them */
- if( !isMD5const )
- {
- memcpy( mConst, md5const, MD5_ROUNDS * sizeof( LONG ) );
- isMD5const = TRUE;
- }
- }
- else
- {
- /* Copy the values to the mConst array, with endianness conversion
- if necessary */
- memcpy( mConst, buffer, MD5_ROUNDS * sizeof( LONG ) );
- #ifdef LITTLE_ENDIAN
- longReverse( mConst, MD5_ROUNDS * sizeof( LONG ) );
- #endif /* LITTLE_ENDIAN */
- isMD5const = FALSE;
- }
- }
-
- /* The routine MD5Init initializes the message-digest context mdContext. All
- fields are set to zero */
-
- void MD5Init( MD5_CTX *mdContext )
- {
- mdContext->i[ 0 ] = mdContext->i[ 1 ] = 0L;
-
- /* Load magic initialization constants */
- mdContext->buf[ 0 ] = 0x67452301L;
- mdContext->buf[ 1 ] = 0xEFCDAB89L;
- mdContext->buf[ 2 ] = 0x98BADCFEL;
- mdContext->buf[ 3 ] = 0x10325476L;
-
- /* Set up the Mysterious Constants if necessary */
- if( !isMD5const )
- {
- memcpy( cryptBuffer, mConst, MD5_ROUNDS * sizeof( LONG ) );
- MD5SetConst( NULL );
- }
- }
-
- /* The routine MD5Update updates the message-digest context to account for
- the presence of each of the characters inBuf[ 0 .. inLen-1 ] in the
- message whose digest is being computed. This is an optimized version
- which assumes that the buffer is a multiple of MD5_BLOCKSIZE bytes long */
-
- #ifdef __MSDOS__
-
- void MD5Update( MD5_CTX *mdContext, BYTE *buffer, unsigned int noBytes )
- {
- int bufIndex = 0;
-
- /* Update number of bits */
- if( ( mdContext->i[ 0 ] + ( ( LONG ) noBytes << 3 ) ) < mdContext->i[ 0 ] )
- mdContext->i[ 1 ]++; /* Carry from low to high bitCount */
- mdContext->i[ 0 ] += ( ( LONG ) noBytes << 3 );
- mdContext->i[ 1 ] += ( ( LONG ) noBytes >> 29 );
-
- /* Process data in MD5_BLOCKSIZE chunks */
- while( noBytes >= MD5_BLOCKSIZE )
- {
- MD5Transform( mdContext->buf, ( LONG * ) ( buffer + bufIndex ) );
- bufIndex += MD5_BLOCKSIZE;
- noBytes -= MD5_BLOCKSIZE;
- }
-
- /* Handle any remaining bytes of data. This should only happen once
- on the final lot of data */
- memcpy( mdContext->in, buffer + bufIndex, noBytes );
- }
-
- /* The routine MD5Final terminates the message-digest computation and ends
- with the desired message digest in mdContext->digest[ 0 ... 15 ] */
-
- void MD5Final( MD5_CTX *mdContext )
- {
- int count;
- LONG lowBitcount = mdContext->i[ 0 ], highBitcount = mdContext->i[ 1 ];
-
- /* Compute number of bytes mod 64 */
- count = ( int ) ( ( lowBitcount >> 3 ) & 0x3F );
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- ( ( BYTE * ) mdContext->in )[ count++ ] = 0x80;
-
- /* Pad out to 56 mod 64 */
- if( count > 56 )
- {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset( ( BYTE * ) &mdContext->in + count, 0, 64 - count );
- MD5Transform( mdContext->buf, ( LONG * ) mdContext->in );
-
- /* Now fill the next block with 56 bytes */
- memset( &mdContext->in, 0, 56 );
- }
- else
- /* Pad block to 56 bytes */
- memset( ( BYTE * ) &mdContext->in + count, 0, 56 - count );
-
- /* Append length in bits and transform */
- ( ( LONG * ) mdContext->in )[ 14 ] = lowBitcount;
- ( ( LONG * ) mdContext->in )[ 15 ] = highBitcount;
-
- MD5Transform( mdContext->buf, ( LONG * ) mdContext->in );
-
- /* Store buffer in digest */
- memcpy( mdContext->digest, mdContext->buf, 16 );
-
- /* Restore the previous Mysterious Constants */
- memcpy( mConst, cryptBuffer, MD5_ROUNDS * sizeof( LONG ) );
- isMD5const = FALSE;
- }
-
- #else
-
- void MD5Update( MD5_CTX *mdContext, BYTE *inBuf, unsigned int inLen )
- {
- int mdi;
- LONG in[ 16 ];
- unsigned int i, ii;
-
- /* Compute number of bytes mod 64 */
- mdi = ( int ) ( ( mdContext->i[ 0 ] >> 3 ) & 0x3F );
-
- /* Update number of bits */
- if( ( mdContext->i[ 0 ] + ( ( LONG ) inLen << 3 ) ) < mdContext->i[ 0 ] )
- mdContext->i[ 1 ]++; /* Carry from low to high bitCount */
- mdContext->i[ 0 ] += ( ( LONG ) inLen << 3 );
- mdContext->i[ 1 ] += ( ( LONG ) inLen >> 29 );
-
- while( inLen-- )
- {
- /* Add new character to buffer, increment mdi */
- mdContext->in[ mdi++ ] = *inBuf++;
-
- /* Transform if necessary */
- if( mdi == 0x40 )
- {
- for( i = 0, ii = 0; i < 16; i++, ii += 4 )
- in[ i ] = ( ( ( LONG ) mdContext->in[ ii + 3 ] ) << 24 ) | \
- ( ( ( LONG ) mdContext->in[ ii + 2 ] ) << 16 ) | \
- ( ( ( LONG ) mdContext->in[ ii + 1 ] ) << 8 ) | \
- ( ( LONG ) mdContext->in[ ii ] );
- MD5Transform( mdContext->buf, in );
- mdi = 0;
- }
- }
- }
-
- /* The routine MD5Final terminates the message-digest computation and ends
- with the desired message digest in mdContext->digest[ 0 ... 15 ] */
-
- void MD5Final( MD5_CTX *mdContext )
- {
- int mdi, padLen;
- BYTE padding[ 64 ];
- unsigned int i, ii;
- LONG in[ 16 ];
-
- /* Save number of bits */
- in[ 14 ] = mdContext->i[ 0 ];
- in[ 15 ] = mdContext->i[ 1 ];
-
- /* Compute number of bytes mod 64 */
- mdi = ( int ) ( ( mdContext->i[ 0 ] >> 3 ) & 0x3F );
-
- /* Pad out to 56 mod 64 */
- padLen = ( mdi < 56 ) ? ( 56 - mdi ) : ( 120 - mdi );
- padding[ 0 ] = 0x80;
- memset( padding + 1, 0, padLen - 1 );
- MD5Update( mdContext, padding, padLen );
-
- /* Append length in bits and transform */
- for( i = 0, ii = 0; i < 14; i++, ii += 4 )
- in[ i ] = ( ( ( LONG ) mdContext->in[ ii + 3 ] ) << 24 ) | \
- ( ( ( LONG ) mdContext->in[ ii + 2 ] ) << 16 ) | \
- ( ( ( LONG ) mdContext->in[ ii + 1 ] ) << 8 ) | \
- ( ( LONG ) mdContext->in[ ii ] );
- MD5Transform( mdContext->buf, in );
-
- /* Store buffer in digest */
- for( i = 0, ii = 0; i < 4; i++, ii += 4 )
- {
- mdContext->digest[ ii ] = ( BYTE ) ( mdContext->buf[ i ] & 0xFF );
- mdContext->digest[ ii + 1 ] = ( BYTE ) ( ( mdContext->buf[ i ] >> 8 ) & 0xFF );
- mdContext->digest[ ii + 2 ] = ( BYTE ) ( ( mdContext->buf[ i ] >> 16 ) & 0xFF );
- mdContext->digest[ ii + 3 ] = ( BYTE ) ( ( mdContext->buf[ i ] >> 24 ) & 0xFF );
- }
-
- /* Restore the previous Mysterious Constants */
- memcpy( mConst, cryptBuffer, MD5_ROUNDS * sizeof( LONG ) );
- isMD5const = FALSE;
- }
- #endif /* !__MSDOS__ */
-